﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using KinectTD.Input;
using KinectTD.Agents;
namespace KinectTD.Towers
{

    public enum UPGRADE_TYPE { RANGE, SPEED, DAMAGE}
    public abstract class Tower
    {

        protected Vector2 position;
        protected Texture2D texture;

        private Texture2D radiusTexture;



        protected Texture2D ammoTexture;
        protected int cost;

        public int Cost
        {
            get { return cost; }
        }

        public int UpgradeCost
        {
            get { return (int)(cost * 1.5); }
        }

        //We need a list of enemies which we shoot at, and a list of bullets which are in our radius
        protected List<Enemy> enemyList;
        protected List<Bullet> activeBullets;

        //Used to show more feedback
        protected bool isHovered = false;
        protected float rangeRadius;
        protected float radius;
        public Vector2 Origin
        {
            get { return new Vector2(position.X + (size.X / 2), position.Y + (size.Y / 2)); }
        }

        //Damage for the bullets
        protected float damage = 15f;
        protected float shootSpeed = 200;
        protected float bulletSpeed = 5f;

        public BULLET_TYPE TowerType = BULLET_TYPE.NORMAL;

        //Used for shooting at set intervals (and any special attack things)
        protected float timer = 0;

        protected Vector2 size;

        protected bool isButton = false;

        public bool IsButton
        {
            get { return isButton; }
            set { isButton = value; }
        }

        protected bool active = false;

        public bool Active
        {
            get { return active; }
            set { active = value; }
        }

        public float RangeRadius
        {
            get { return rangeRadius; }
        }

        public float Radius
        {
            get { return radius; }
        }

        public Vector2 Size
        {
            get { return size; }
            set { size = value; }
        }

        //Rectangle we draw to
        public Rectangle drawRect
        {
            get { return new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y); }
        }

        //The rectangle showing the range radius image.
        protected Rectangle radiusRangeRect
        {
            get
            {
                return new Rectangle((int)(Origin.X - rangeRadius),
                         (int)(Origin.Y - rangeRadius),
                          (int)rangeRadius * 2,
                          (int)rangeRadius * 2);
            }
        }
        //The rectangle showing the radius which towers can be placed with.
        protected Rectangle radiusRect
        {
            get
            {
                return new Rectangle((int)(Origin.X - radius),
                                (int)(Origin.Y - radius),
                                 (int)radius * 2,
                                 (int)radius * 2);
            }
        }

        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }

        public Tower(Vector2 towerPosition, Texture2D towerTexture, Texture2D radiusTexture, List<Enemy> enemyList, Texture2D bulletTexture)
        {
            position = towerPosition;
            texture = towerTexture;
            this.radiusTexture = radiusTexture;
            this.enemyList = enemyList;
            activeBullets = new List<Bullet>();
            ammoTexture = bulletTexture;
            cost = 100;
            radius = 150;

        }

        public void Upgrade(UPGRADE_TYPE type)
        {
            switch(type)
            {
                case UPGRADE_TYPE.DAMAGE:
                    this.damage *= 1.5f;
                    break;
                case UPGRADE_TYPE.RANGE:
                    this.rangeRadius *= 1.5f;
                    break;
                case UPGRADE_TYPE.SPEED:
                    this.shootSpeed -= (this.shootSpeed) * 1.5f;
                    break;
            }
        }


        public virtual void Update(GameTime gameTime)
        {
            //Add to the time since the last tick
            timer += gameTime.ElapsedGameTime.Milliseconds * Engine.GAME_SPEED;



            if (active)
            {
                for (int i = 0; i < activeBullets.Count; ++i)
                {
                    Bullet b = activeBullets[i];

                    //Remove any bullets which are not in our radius anymore
                    Vector2 pDiff = Origin - b.Origin;
                    float distance = pDiff.Length();
                    if (!Engine.CheckCollision(Origin, b.Origin, rangeRadius, b.CollisionRadius))
                    {

                        activeBullets.Remove(b);

                    }
                    //Update the survivors
                    b.Update(gameTime);


                }

                //If it is time to shoot - then shoot.
                if (timer >= shootSpeed)
                {
                    foreach (Enemy e in enemyList)
                    {
                        //If the enemy is in the RECTANGLE of the tower radius, then target it (adds for a more realistic, close enough, even though they can't be hit in this position)
                        if (radiusRangeRect.Contains((int)e.Position.X, (int)e.Position.Y))
                        {
                            Vector2 pos = new Vector2(position.X + (size.X / 2), position.Y + (size.Y / 2));
                            Vector2 shootVector = e.Origin - Origin;
                            Bullet b = new Bullet(shootVector, bulletSpeed, pos, ammoTexture, damage, enemyList);
                            b.BTYPE = TowerType;
                            activeBullets.Add(b);
                            break;
                        }
                    }
                    timer = 0;
                }
            }


            if (drawRect.Contains(Kinect.CursorPosition))
                isHovered = true;
            else
                isHovered = false;


        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {

            if (!isButton)
            {
                if (isHovered)
                {
                    spriteBatch.Draw(radiusTexture, radiusRangeRect, Color.Red);

                    spriteBatch.Draw(Engine.DamageTexture, new Rectangle((int)position.X + 30, (int)position.Y - 75, Engine.DamageTexture.Width / 3, Engine.DamageTexture.Height / 3), Color.White);
                    spriteBatch.Draw(Engine.RangeTexture, new Rectangle((int)position.X + 35, (int)position.Y - 40, Engine.RangeTexture.Width / 4, Engine.RangeTexture.Height / 4), Color.White);
                    spriteBatch.Draw(Engine.SpeedTexture, new Rectangle((int)position.X + 35, (int)position.Y - 15, Engine.SpeedTexture.Width / 3, Engine.SpeedTexture.Height / 3), Color.White);
                    spriteBatch.DrawString(Engine.UtilFont, "" + damage * 100, new Vector2(position.X + 60, position.Y - 65), Color.White);
                    spriteBatch.DrawString(Engine.UtilFont, "" + rangeRadius * 2, new Vector2(position.X + 60, position.Y - 45), Color.White);
                    spriteBatch.DrawString(Engine.UtilFont, "" + shootSpeed, new Vector2(position.X + 60, position.Y - 25), Color.White);
                }

                if (!active)
                    spriteBatch.Draw(radiusTexture, radiusRect, Color.White);

                foreach (Bullet b in activeBullets)
                    b.Draw(spriteBatch);
            }

            spriteBatch.Draw(texture, drawRect, Color.White);


        }



    }
}
